﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;

namespace mana.Web.UI
{
    public class PageBase : Page
    { 
        /// <summary>
        /// Gets a strongly typed value from ViewState.
        /// </summary>
        /// <typeparam name="T">Value's type.</typeparam>
        /// <param name="name">The value's name to get.</param>
        /// <returns>The value stored in ViewState with the specified name.\n
        /// If there's no value set with the specified name, it returns the default value for the specified type.</returns>
        public T GetFromViewState<T>(string name)
        {
            if (ViewState[name] == null)
                return default(T);

            return (T)ViewState[name];
        }

        /// <summary>
        /// Sets a strongly typed value to ViewState.
        /// </summary>
        /// <typeparam name="T">Value's type.</typeparam>
        /// <param name="name">The value's name to set.</param>
        /// <param name="value">The value to set in ViewState.</param>
        public void SetToViewState<T>(string name, T value)
        {
            if (ViewState[name] == null)
                ViewState.Add(name, value);
            else
                ViewState[name] = value;
        }

        /// <summary>
        /// Gets a strongly typed value from Session.
        /// </summary>
        /// <typeparam name="T">Value's type.</typeparam>
        /// <param name="name">The value's name to get.</param>
        /// <returns>The value stored in Session with the specified name.\n
        /// If there's no value set with the specified name, it returns the default value for the specified type.</returns>
        public T GetFromSession<T>(string name)
        {
            if (Session[name] == null)
                return default(T);

            return (T)Session[name];
        }

        /// <summary>
        /// Sets a strongly typed value to Session.
        /// </summary>
        /// <typeparam name="T">Value's type.</typeparam>
        /// <param name="name">The value's name to set.</param>
        /// <param name="value">The value to set in Session.</param>
        public void SetToSession<T>(string name, T value)
        {
            if (Session[name] == null)
                Session.Add(name, value);
            else
                Session[name] = value;
        }

        /// <summary>
        /// Stores a cookie for the authenticated user specified.
        /// Creates a persistent cookie by default.
        /// </summary>
        /// <param name="username">The authenticated username.</param>
        public void SetAuthenticatedUserCookieAndRedirectToDefaultPage(string username)
        {
            SetAuthenticatedUserCookieAndRedirectToDefaultPage(username, true);
        }

        /// <summary>
        /// Stores a cookie for the authenticated user specified.
        /// </summary>
        /// <param name="username">The authenticated username.</param>
        /// <param name="persistentCookie">Indicates wheter to create a persistent cookie or not.</param>
        public void SetAuthenticatedUserCookieAndRedirectToDefaultPage(string username, bool persistentCookie)
        {
            FormsAuthentication.RedirectFromLoginPage(username, persistentCookie);
        }

        /// <summary>
        /// Redirects to Login page, keeping the existing QueryString.
        /// </summary>
        public void RedirectsToLoginPage()
        {
            FormsAuthentication.RedirectToLoginPage();
        }

        /// <summary>
        /// Redirects to Login page, keeping the existing QueryString and adding extra values to it.
        /// NOTE: The extra string works only for the Login page, it's not added to the Return url.
        /// </summary>
        /// <param name="extraQueryString"></param>
        public void RedirectsToLoginPage(string extraQueryString)
        {
        FormsAuthentication.RedirectToLoginPage(extraQueryString);
        }

        /// <summary>
        /// Shows a message in the specified Label Control.
        /// </summary>
        /// <param name="label">Label Control.</param>
        /// <param name="message">Message to show.</param>
        public void ShowMessage(Label label, string message)
        {
            ShowMessage(label, message, null);
        }

        /// <summary>
        /// Shows a message in the specified Label Control.
        /// </summary>
        /// <param name="label">Label Control.</param>
        /// <param name="message">Message to show.</param>
        /// <param name="cssClass">Css class to apply to Label.</param>
        public void ShowMessage(Label label, string message, string cssClass)
        {
            if (label == null)
                throw new ArgumentNullException("label");

            if (!string.IsNullOrWhiteSpace(cssClass))
                label.CssClass = cssClass;

            label.Text = message;
        }

        /// <summary>
        /// Clears the message from the specified Label Control.
        /// </summary>
        /// <param name="label">Label Control.</param>
        public void ClearMessage(Label label)
        {
            if (label == null)
                throw new ArgumentNullException("label");

            label.Text = string.Empty;
        }

        /// <summary>
        /// Shows a file download dialog for the specified file.
        /// NOTE: This method will ALWAYS throw an ThreadAbortedException which is normal (it works anyways), since it's rewriting the actual Response.
        /// </summary>
        /// <param name="fileName">File name.</param>
        /// <param name="fileStream">File stream.</param>
        public void ShowFileDownloadDialog(string fileName, Stream fileStream)
        {
            int fileLength = (int)fileStream.Length;

            var fileBytes = new byte[fileStream.Length];
            using (var reader = new BinaryReader(fileStream))
            {
                reader.Read(fileBytes, 0, fileLength);
            }

            ShowFileDownloadDialog(fileName, fileBytes);
        }

        /// <summary>
        /// Shows a file download dialog for the specified file.
        /// NOTE: This method will ALWAYS throw an ThreadAbortedException which is normal (it works anyways), since it's rewriting the actual Response.
        /// </summary>
        /// <param name="fileName">File name.</param>
        /// <param name="fileStream">File path.</param>
        public void ShowFileDownloadDialog(string fileName, string path)
        {
            int fileLength = 0;
            var fileBytes = new byte[0];

            using (var fileStream = File.OpenRead(path))
            {
                fileLength = (int)fileStream.Length;

                fileBytes = new byte[fileStream.Length];
                fileStream.Read(fileBytes, 0, fileLength);
            }

            ShowFileDownloadDialog(fileName, fileBytes);
        }

        /// <summary>
        /// Shows a file download dialog for the specified file.
        /// NOTE: This method will ALWAYS throw an ThreadAbortedException which is normal (it works anyways), since it's rewriting the actual Response.
        /// </summary>
        /// <param name="fileName">File name.</param>
        /// <param name="fileBytes">File bytes.</param>
        public void ShowFileDownloadDialog(string fileName, byte[] fileBytes)
        {
            if (string.IsNullOrWhiteSpace(fileName))
                throw new ArgumentNullException("filename");
            
            Response.Clear();
            Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
            Response.AddHeader("Content-Length", fileBytes.Length.ToString());
            Response.ContentType = MimeTypes.GetFileMimeType(fileName);
            Response.BinaryWrite(fileBytes);
            Response.End();
        }
    }
}
